#include <string>
#include "AudioDecoder.h"

#include "Media/Sync/sync.h"
AudioDecoder::AudioDecoder():codec_ctx_(nullptr) {

}

AudioDecoder::~AudioDecoder() {
  //  release();
}
bool AudioDecoder::init(const AVCodecContextPtr& codec_ctx) {

    codec_ctx_ = codec_ctx.get();
    if(codec_ctx_ == nullptr){
        std::cout << "Error: init codec context is null." << std::endl;
        return false;
    }
    std::call_once(printf_audioinfo_flag_, [&](){
        std::cout << "Called once" << std::endl;
        const char* sample_fmt_name = av_get_sample_fmt_name(codec_ctx_->sample_fmt);
        //5.解码器支持的输入格式
        std::cout << "Name of sample_fmt: " << sample_fmt_name << std::endl;




        // 获取并打印声道数量
        std::cout << "Number of channels: " << codec_ctx_->ch_layout.nb_channels << std::endl;
        // 创建一个足够大的缓冲区来保存声道布局的描述
        char buf[1024];

        // 7.获取并打印声道布局的描述
        int ret = av_channel_layout_describe(&codec_ctx_->ch_layout, buf, sizeof(buf));
        if (ret < 0) {
            std::cerr << "Failed to get channel layout description" << std::endl;
        } else {
            std::cout << "Channel layout description: " << buf << std::endl;
        }
        //8.解码器的延迟
        // std::cout << "delay: " << codec_ctx_->delay << std::endl;
        // std::cout << "delay: " << codec_ctx_->delay << std::endl;
        // 打印 ch_layout 的值
        //   std::cout << "ch_layout value: " << static_cast<uint64_t>(av_layout) << std::endl;
    });

    return true;

}
//{
//    //    // 初始化 SwrContext
//    //    struct SwrContext* swr = NULL;
//    //    int64_t out_ch_layout = AV_CH_LAYOUT_STEREO;
//    //    int64_t in_ch_layout = AV_CH_LAYOUT_STEREO;

//    //    int result = swr_alloc_set_opts2(&swr,
//    //        (AVChannelLayout *) &out_ch_layout, AV_SAMPLE_FMT_S16, 44100,
//    //        (AVChannelLayout *) &in_ch_layout, AV_SAMPLE_FMT_FLTP, 44100,
//    //        0, NULL);

//    //    if (result < 0) {
//    //        // Handle error
//    //    }

//    //    swr_init(swr);
//}
bool AudioDecoder::decode(AVPacket* packet) {
    // std::this_thread::sleep_for(std::chrono::milliseconds(10));
    int decode_ret = false;
    if(packet == NULL){
        std::cout << "Error: decode packet context is null." << std::endl;
        return false;
    }

    if(codec_ctx_ == NULL){
        std::cout << "Error: decode codec context is null." << std::endl;
        return false;
    }

    int ret = avcodec_send_packet(const_cast<AVCodecContext*>(codec_ctx_), packet);
    if (ret < 0) {
        std::cout << "Error: avcodec_send_packet failed with error code " << ret << std::endl;
        return false;
    }


    AVFrame* frame = av_frame_alloc();
    if (!frame) {
        std::cout << "Error: av_frame_alloc failed." << std::endl;
        return false;
    }

    while (ret >= 0) {
        ret = avcodec_receive_frame(const_cast<AVCodecContext*>(codec_ctx_), frame);
        if (ret == AVERROR(EAGAIN)) {
      //      std::cout << "Info: avcodec_receive_frame returned EAGAIN." << std::endl;
//            char errbuf[AV_ERROR_MAX_STRING_SIZE];
//            av_strerror(ret, errbuf, sizeof(errbuf));
//            std::cout << "Error:"<< errbuf << std::endl;
            goto decoder_fail;
        }else if(ret == AVERROR_EOF){
            std::cout << "Info: avcodec_receive_frame returned AVERROR_EOF." << std::endl;
            goto decoder_fail;
        }
        else if (ret < 0) {
            std::cout << "Error: avcodec_receive_frame failed with error code " << ret << std::endl;
            goto decoder_fail;
        }
        AVSync::getInstance().add_audio_frame(frame);
        decode_ret = true;

 //       std::cout << "Info: Successfully processed a frame." << std::endl;
        // Remember to unref the frame after processing.
        av_frame_unref(frame);
    }

    av_frame_free(&frame);
decoder_fail:
//    std::cout << "Info: Successfully decoded the packet." << std::endl;
    return decode_ret;
  av_frame_free(&frame);
  return decode_ret;
}
void AudioDecoder::release() {
    codec_ctx_ = nullptr;
}
